#ifndef MOCHA_DETAIL_MEMORY_HPP_INCLUDED
#define MOCHA_DETAIL_MEMORY_HPP_INCLUDED

/**
 * @file 
 */

#include <cstdint>

#if defined(__GNUC__)
	/**
	 * Expands to a packing attribute for aggregate types (for supported compilers).
	 */
	#define MOCHA_PACKED __attribute__((__packed__))
	/**
	 * Expands to an alignment attribute for aggregate types (for supported compilers).
	 * @param bytes Alignment. Aligns to at least this many bytes (for most compilers).
	 */
	#define MOCHA_ALIGNED(bytes) __attribute__((__aligned__(bytes)))
#elif defined(__MSVC__)
	#define MOCHA_PACKED
	#define MOCHA_ALIGNED(bytes) __declspec(align(bytes))
#elif
	#define MOCHA_PACKED
	#define MOCHA_ALIGNED(bytes)
#endif

/**
 * Expands to the stride of an aggregate type.
 * @param T 
 */
#define MOCHA_STRIDEOF(T) \
((sizeof(mocha::detail::stride_detector<T>) > sizeof(T)) ? sizeof(mocha::detail::stride_detector<T>) - sizeof(T) : sizeof(T))

namespace mocha {

namespace detail {
template<typename T>
struct stride_detector {
	T t;
	std::int8_t i;
};
}

/**
 * A strideof operator.
 * Provides a mechanism for finding the memory stride of an aggregate type.
 * @param T 
 * @see MOCHA_STRIDEOF
 */
template<typename T>
struct strideof {
	enum {
		/// Stride.
		stride = MOCHA_STRIDEOF(T)
	};
};
}

#endif

